﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace ExpressionToWhere
{
    /// <summary>
    /// 将worker => !(worker.Age == 1)转化成worker => worker.Age != 1
    /// </summary>
    internal class UnaryBinaryExpressionVisitor : BaseExpressionVisitor
    {
        public UnaryBinaryExpressionVisitor(bool searchNull = true, string dbType = "SqlServer") : base(searchNull, dbType)
        {

        }

        protected override Expression VisitUnary(UnaryExpression node)
        {
            BinaryExpression binaryExp = node.Operand as BinaryExpression;
            if (node.NodeType == ExpressionType.Not && binaryExp != null)
            {
                binaryExp = GetOppositeExpression(binaryExp);
                sb.Append($"{ExpressionProcesser.GetWhereClause(binaryExp, searchNull, dbType)}");
            }
            else
            {
                throw new NotSupportedException($"Unknow UnaryExpression:{node}");
            }
            return node;
        }

        /// <summary>
        /// 对BinaryExpression所用的运算符取反
        /// </summary>
        /// <param name="binaryExp"></param>
        /// <returns></returns>
        private static BinaryExpression GetOppositeExpression(BinaryExpression binaryExp)
        {
            switch (binaryExp.NodeType)
            {
                case ExpressionType.Equal:
                    return BinaryExpression.NotEqual(binaryExp.Left, binaryExp.Right);
                case ExpressionType.GreaterThan:
                    return BinaryExpression.LessThanOrEqual(binaryExp.Left, binaryExp.Right);
                case ExpressionType.GreaterThanOrEqual:
                    return BinaryExpression.LessThan(binaryExp.Left, binaryExp.Right);
                case ExpressionType.LessThan:
                    return BinaryExpression.GreaterThanOrEqual(binaryExp.Left, binaryExp.Right);
                case ExpressionType.LessThanOrEqual:
                    return BinaryExpression.GreaterThan(binaryExp.Left, binaryExp.Right);
                case ExpressionType.NotEqual:
                    return BinaryExpression.Equal(binaryExp.Left, binaryExp.Right);
                default:
                    return binaryExp;
            }
        }
    }
}
